%option noyywrap
%{
#include <stdlib.h>
#include <string.h>
#include "tree_dstruct.h"
#include "parser.tab.h"

#define RED     "\x1b[31m"
#define GREEN   "\x1b[32m"
#define YELLOW  "\x1b[33m"
#define BLUE    "\x1b[34m"
#define CYAN    "\x1b[36m"
#define CLR     "\x1b[0m"

#ifdef LEX_DBG
#define dbg(...)		printf(__VA_ARGS__)
#else
#define dbg(...)		
#endif

#define	SET_STATUS(a)		if(status == 0) { status=a; }


long print_num(void);
void err_unexpected_char(void);


long line = 1;
extern int status;
//int status = 0;
%}

DIGIT				[0-9]
CHAR				[a-zA-Z]
LEXEMA				";"|"("|")"|","|":"|"="|">"|"["|"]"|"-"|"+"|"*"

%x comment
%%

"end"				dbg("end\n"); return END;
"return"			dbg("return\n"); return RETURN;
"goto"				dbg("goto\n"); return GOTO;
"if"				dbg("if\n"); return IF;
"var"				dbg("var\n"); return VAR;
"and"				dbg("and\n"); return AND;
"not"				dbg("not\n"); return NOT;
"(*"				BEGIN(comment);
<comment>[ \n\r]		line++;
<comment>[^*]*			/* nada */
<comment>"*"+[^)]		/* nada */
<comment>"*"+")"		BEGIN(0);
{CHAR}({CHAR}|{DIGIT})*		{
		dbg("id: %s\n", yytext);
		yylval.id.line = line;
		yylval.id.name = strdup(yytext);
		return ID;
				}
({DIGIT}|"_")+			{
		yylval.num.line = line;
		yylval.num.val = print_num();
		return NUM;
				}
{LEXEMA}			dbg("lx: %c\n", *yytext); return (int) *yytext;
"!="				dbg("!=\n"); return NEQ;
[\r\n]				line++;
[ \t\xD]+			/* nada */
<<EOF>>				dbg("EOF\n"); return 0;
.				err_unexpected_char(); return 0;

%%

void err_unexpected_char() {
	SET_STATUS(1);
	printf(RED "[Parse Error]" CLR GREEN ": %ld " CLR "unexpected char" CYAN " %s " CLR "\n", line, yytext);

}

long print_num(void) {
	char mem[8] = {0};
	char *num, *numrun = mem;
	num = mem;
	char *yyrun = yytext;
	int i = 0;
	long result;

	while(i < yyleng) {
		if((*yyrun) != '_')
			(*numrun++) = (*yyrun);
		yyrun++;
		i++;
	}

	numrun = num;
	result = strtol(numrun, &numrun, 10);
	dbg("num %ld\n", result);
	return result;
}
